package cn.biplam.back.bean.tool.flat;

import java.util.ArrayList;

import cn.biplam.back.bean.ddl.Sql2Db;
import cn.biplam.back.jda.Jda;
import cn.biplam.back.sql.ddl.Field;
import cn.biplam.back.sql.ddl.Table;
import cn.biplam.back.sql.dml.Insert;
import cn.biplam.back.sql.type.Int;
import cn.biplam.back.sql.type.VarChar;
import cn.biplam.common.bean.sqlengine.Sql;
import cn.biplam.common.client.DbResource;
import cn.biplam.common.tools.DEBUG;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.treeFlat.PcNode;
import cn.biplam.common.wrapper.treeFlat.flat.FlatOut;

/**
 *  创建平面关系数据表到数据库<BR>
 * 用法： 1 创建: 传入树形数据结构创建<BR>
 *       2 设置平面关系表表名 setTargetTableName(表名)<BR>
 *       3 设置目标数据源 setTargetDbResource(数据源)<BR>
 *       4 执行创建 toDb<BR>
 * @author XiaoRuxing Nov 28, 200911:11:15 AM
 * @version 1.0
 */
public class FlatToDb extends FlatOut{

	/**  */
	private String tableName;
	private DbResource trgDb;
	private Jda mJda;
	private boolean ignoreSqlError;

	/**
	 *  创建平面化数据
	 * @param data 平面化数据
	 */
	public FlatToDb(PcNode data) {
		super(data);
	}

	/**
	 *  设置目标表表名称
	 * @param tableName 表名称
	 */
	public void setTargetTableName(String tableName){
		this.tableName = tableName;
	}
	
	/**
	 *  设置目标数据源
	 * @param trgDb 目标数据源
	 */
	public void setTargetDbResource(DbResource trgDb){
		this.trgDb = trgDb;
	}
	
	/**
	 * @return 平面化是否成功
	 */
	public boolean toDb(boolean ignoreSqlError) throws ErrorMessage{
		if(this.tableName == null ||
				this.trgDb == null){
			throw new ErrorMessage("Flat target table or target database is null at FloatTodb!");
		}
		this.ignoreSqlError = ignoreSqlError;
		this.treeFlat.execute();
		//获取字段列表
		this.getFieldNameList();
		mJda = new Jda(trgDb,false);
		try{
			//创建表
			this.createTable();
			//插入数据
			this.insertData();
			return true;
		}catch (ErrorMessage e) {
			DEBUG.println("\n【Error】\t"+e.getMessage());
		}catch(Exception e){
			DEBUG.println("\n【Error】\t"+e.getMessage());
		}finally{
			mJda.connClose();
		}
		//将数据插入表
		return false;
	}

	/**
	 * @return 平面表创建器
	 */
	private void createTable() throws ErrorMessage{
		//创建平面表
		Table table = new Table(this.tableName, this.trgDb);
		//创建平面表字段
		//创建ID字段
		Field id = 
			new Field(this.nodeIdField,new VarChar(50));
		table.put(id);
		//创建名称字段
		Field name = 
			new Field(this.nodeNameField,new VarChar(200));
		table.put(name);
		//创建业务级别字段
		if(this.nodeLevelField!=null){
			Field level = 
				new Field(this.nodeLevelField,new Int());
			table.put(level);
		}
		//创建节点类型字段
		if(this.operatorTypeFieldName!=null){
			Field operatorType = 
				new Field(this.operatorTypeFieldName,new VarChar(2));
			table.put(operatorType);
		}
		//创建父亲们字段
		for(String parentId:parentFieldNameList){
			Field parent = 
				new Field(parentId,new VarChar(50));
			table.put(parent);
		}
		for(String parentName:parentNameFieldNameList){
			Field parent = 
				new Field(parentName,new VarChar(200));
			table.put(parent);
		}
		ArrayList<Table> tables = new ArrayList<Table>();
		tables.add(table);
		Sql2Db db = new Sql2Db(this.trgDb,tables);
		db.ddlExecute(true);
	}

	/**
	 *  插入平面化数据
	 * @throws ErrorMessage
	 */
	private void insertData() throws ErrorMessage{
		while(this.treeFlat.next()){
			String[] curData = this.treeFlat.getCurentNode();
			Insert insert = new Insert(this.tableName);
			insert.putStringFieldDenyNull(this.nodeIdField, curData[0]);
			insert.putStringFieldIgnoreNull(this.nodeNameField, curData[1]);
			if(this.nodeLevelField!=null){
				insert.putFieldIgnoreNull(this.nodeLevelField, curData[2]);
			}
			if(this.operatorTypeFieldName!=null){
				insert.putStringFieldIgnoreNull(this.operatorTypeFieldName, curData[3]);
			}
			int numb=4;
			for(int i=0;i<parentFieldNameList.size();i++){
				insert.putStringFieldIgnoreNull(parentFieldNameList.get(i),
						curData[i+numb]);
			}
			numb = numb+this.treeFlat.getDepth();
			for(int i=0;i<parentNameFieldNameList.size();i++){
				insert.putStringFieldIgnoreNull(parentNameFieldNameList.get(i),
						curData[i+numb]);
			}
			//执行插入语句
			this.execute(insert.getSimpleSql(), mJda);
		}
	}

	/**
	 *  执行SQL语句
	 */
	private void execute(String sql,Jda mJda) throws ErrorMessage{
		try {
			mJda.executeDDL(new Sql(sql));
		} catch (ErrorMessage e) {
			if(ignoreSqlError){
				DEBUG.println("【Warnning】\t"+e.getMessage());
			}else
				throw e;
		} catch (Exception e){
			throw new ErrorMessage(e,sql);
		}
	}
}
